
package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"

	"gitee.com/wmdng/cv1800b/genfs/fat16"
	"gitee.com/wmdng/cv1800b/genfs/rbfs"
)



type VirtFS interface {
	Create( fnm string ) (io.WriteCloser, error)
	FlushTo( wfd io.WriteSeeker ) error 
}



func printUsage( efn string,  erstr string )  {

	if len(erstr) > 0  {
		fmt.Printf( "err: %s\n", erstr )
	}

	fmt.Println( "usage:" )
	fmt.Printf( "%s <fat16 | rbfs> <dirname> <max-sector>\n", efn )
	return
}


func main()  {

	var fatfs bool
	var vfs VirtFS

	if len(os.Args) < 4 {
		printUsage( os.Args[0], "" )
		return
	}
	
	if (os.Args[1] == "fat16") || (os.Args[1] == "fat")  {
		fatfs = true
	} else if os.Args[1] == "rbfs"  {
		fatfs = false
	} else {
		printUsage( os.Args[1], "fs not supported..." )
		return
	}

	// check dir..
	info, err := os.Stat( os.Args[2] )
	if err != nil {
		printUsage( os.Args[0], fmt.Sprintf( "stat err, %v\n", err) )
		return
	}

	if !info.IsDir()  {
		printUsage( os.Args[0], "args err, Directory path need..")
		return
	}

	// walk through dir...
	ents, err := os.ReadDir( os.Args[2] )
	if err != nil {
		printUsage( os.Args[0], fmt.Sprintf( "read dir err,", err ) )
		return
	}

	if len(ents) <= 0 {
		printUsage( os.Args[0], "read dir err, Directory is empty.." )
		return
	}

	// sector count
	secnt, err := strconv.ParseUint( os.Args[3], 0, 32 )
	if err != nil {
		printUsage( os.Args[0], "read dir err, Directory is empty..")
		return
	}

	if fatfs {
		vfs = fat16.NewFatFs( uint(secnt), false )
	} else {
		vfs = rbfs.NewRBfs( uint(secnt) )
	}


	for _, fent := range ents {

		if !fent.Type().IsRegular() {
			continue
		}

		tinf, _ := fent.Info()
		if tinf.Size() <= 0 {
			continue
		}

		// open file
		sfp, err := os.Open( filepath.Join( os.Args[2], fent.Name() ) )
		if err != nil {
			fmt.Println( "open file err,", err )
			return
		}

		defer sfp.Close()

		dfp, err := vfs.Create( fent.Name() )
		if err != nil {
			fmt.Println( "fs.create err,", err )
			return
		}

		io.Copy( dfp, sfp )
		dfp.Close()
	}

	wfd, err := os.Create( "tempfs.bin" )
	if err != nil {
		fmt.Println( "create file,", err )
		return
	}
	
	defer wfd.Close();

	err = vfs.FlushTo( wfd )
	if err != nil {
		fmt.Println( "flush file,", err )
		return
	}

	
	fmt.Println( "...succ..." )
}



